package io.github.veigara.tcp.device.protocol.charger;

import io.github.veigara.tcp.framework.protocol.ProtocolDecoder;
import io.github.veigara.tcp.framework.utils.BytesUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteOrder;
import java.util.List;

/**
 * @author : zhouhx
 * 充电机协议解码器
 * @date : 2025/6/6 13:54
 */
public class ChargingPileDecoder extends MessageToMessageDecoder<ByteBuf> implements ProtocolDecoder<ChargingPileMessage> {
    private static final Logger logger = LoggerFactory.getLogger(ChargingPileDecoder.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (in.readableBytes() < 9){
            // 最小长度检查
            return;
        }
        ChargingPileMessage message = decode(in);
        if (message != null) {
            out.add(message);
        }
    }

    @Override
    public ChargingPileMessage decode(ByteBuf in) {
        try {
            //根据协议规范解析
//        起始域     长度域     信息域    序列号域  命令代码CMD   数据域     校验和域
//        2 (字节)   2 (字节)  1 (字节)  1 (字节)   2 (字节)   N(字节)    1(字节)
//        0xAA0xF5  0～0x8000 0x10     0～0xFF  消息类型    参考说明    后 8 位
//        本协议中，所有数值长度为 2 字节、4 字节数值数据，均是低位在前，高位在后的小端格式表示
            in.markReaderIndex();
            String hexDump = BytesUtil.hexDumpUpperCaseWithSpace(in);
            logger.debug("Raw message: {}", hexDump);

            int startFlag = in.readUnsignedShort();

            if (startFlag != 0xAAF5) {
                in.resetReaderIndex();
                return null;
            }
            // 设置为小端模式
            ByteBuf littleBuf = in.asReadOnly().order(ByteOrder.LITTLE_ENDIAN);

            int length = littleBuf.readUnsignedShort();
            if (littleBuf.readableBytes() < length - 4) {
                // 减去已读的4字节
                littleBuf.resetReaderIndex();
                return null;
            }

            ChargingPileMessage msg = new ChargingPileMessage();
            msg.setSourceHex(hexDump);
            msg.setStartFlag(startFlag);
            msg.setLength(length);
            msg.setInfoField(littleBuf.readByte());
            msg.setSequence(littleBuf.readByte());
            msg.setCmd(littleBuf.readUnsignedShort());

            int dataLength = length - 9;
            // 总长 - 固定头尾9字节
            msg.setData(littleBuf.readBytes(dataLength));
            // 校检和
            msg.setChecksum(littleBuf.readUnsignedByte());
            if (msg.getChecksum() != msg.calculateChecksum()) {
                throw new IllegalStateException("Checksum error");
            }

            return msg;
        } catch (Exception e) {
            logger.error("Failed to decode charging pile message: {}","" , e);
            return null;
        }
    }
}
